#include "lib/buffer.h"
#include "mm/kalloc.h"

// 创建缓冲区
buffer *std_buffer_create()
{
    buffer *b = (buffer *)kalloc();
    b->cap = DEFAULT_BUFSIZE;
    std_buffer_clear(b);
    return b;
}

// 回收缓冲区
void std_buffer_destroy(buffer *b)
{
    kfree(b);
}

// 重置缓冲区，但不回收存储空间
void std_buffer_clear(buffer *b)
{
    b->size = 0;
    b->head = 0;
    b->tail = 0;
    b->peek = 0;
}

// 向缓冲区 b 存入 1 字节
void std_buffer_put(buffer *b, const byte data)
{
    if (buffer_is_full(b))
        return;
    b->data[b->tail] = data;
    move_next(b->tail, b->cap);
    b->size++;
}

// 向缓冲区 b 存入一串数据
void std_buffer_puts(buffer *b, const char *data)
{
    while (*data != 0)
    {
        std_buffer_put(b, *data);
        data++;
    }
}

// 从缓冲区 b 尾部弹出 1 字节
// 返回弹出值，访问指针和缓冲区尾前移
byte std_buffer_pop_back(buffer *b)
{
    if (buffer_is_empty(b))
        return 0;
    byte data = b->data[b->tail];
    if (buffer_is_empty_peek(b))
        move_prev(b->peek, b->cap);
    move_prev(b->tail, b->cap);
    b->size--;
    return data;
}

// 从缓冲区 b 头部弹出 1 字节
// 返回弹出值，访问指针和缓冲区头后移
byte std_buffer_pop_front(buffer *b)
{
    if (buffer_is_empty(b))
        return 0;
    byte data = b->data[b->head];
    if (buffer_is_full_peek(b))
        move_next(b->peek, b->cap);
    move_next(b->head, b->cap);
    b->size--;
    return data;
}

// 从缓冲区 b 中读取长度为 size 的数据装入 data 数组
int std_buffer_gets(buffer *b, char *data, int size)
{
    int i = 0;
    while (i < size)
    {
        data[i] = std_buffer_pop_front(b);
        if (data[i] == '\n')
        {
            data[i] = 0;
            return i;
        }
        i++;
    }
    if (i == size)
        data[i - 1] = 0;
    return i;
}

// 从缓冲区 b 访问指针的对应位置取出 1 字节
// 返回指针所指值，访问指针后移
byte std_buffer_peek(buffer *b)
{
    if (buffer_is_empty_peek(b))
        return 0;
    byte c = b->data[b->peek];
    move_next(b->peek, b->cap);
    return c;
}

// 访问指针前移
void std_buffer_back(buffer *b)
{
    if (buffer_is_full_peek(b))
        return;
    move_prev(b->peek, b->cap);
}

// 缓冲区 b 等待第一个输入的字符
char std_buffer_wait_char(buffer *b)
{
    while (buffer_is_empty(b))
        nop();
    return std_buffer_pop_front(b);
}

// 从缓冲区 b 中获取一行，数据存入 data，以换行符结束（或数据长度达到 size）
// 换行符将被替换为0。
// 若缓冲区为空，则等待。
int std_buffer_wait_line(buffer *b, char *data, int size)
{
    int i = 0;
    while (i < size)
    {
        while (buffer_is_empty_peek(b))
            nop();
        if (std_buffer_peek(b) == '\n')
            break;
        i++;
    }
    return std_buffer_gets(b, data, size);
}